package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleComputeService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleComputeService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    ApArticleMapper apArticleMapper;

    @Override
    public void hotArticleCompute() {
        //1.查询前5天文章
        Date date = DateTime.now().minusDays(5).toDate();
        List<ApArticle> list = apArticleMapper.findArticleListByDays(date);
        System.out.println(list.size());

        //2.计算每篇文章分值（阅读1分  点赞3分  评论5分  收藏8分）
        List<HotArticleVo> hotArticleVoList = computeArticleScore(list);
        for (HotArticleVo hotArticleVo : hotArticleVoList) {
            System.out.println(hotArticleVo.getTitle()+"---"+hotArticleVo);
        }

        //3.为每个频道缓存分值较高的30篇文章   存redis
        cacheArticleToRedis(hotArticleVoList);
    }


    @Autowired
    IWemediaClient wemediaClient;
    /**
     * 为每个频道 缓存分值较高的30篇 文章到redis
     * @param hotArticleVoList
     */
    private void cacheArticleToRedis(List<HotArticleVo> hotArticleVoList) {
        //feign远程调用  自媒体服务  获取所有频道
        ResponseResult channels = wemediaClient.channels();
        log.info("feign远程调用自媒体服务获取所有频道  {}", channels);
        if(channels!=null && channels.getCode()!=null && channels.getCode().equals(200)){
            String jsonString = JSON.toJSONString(channels.getData());//channels.getData()是json集合对象
            List<WmChannel> wmChannels = JSON.parseArray(jsonString, WmChannel.class);
            if(wmChannels!=null && wmChannels.size()>0){
                for (WmChannel wmChannel : wmChannels) {//外层循环所有频道
                    //内存循环 循环所有的文章,将同一频道下的文章  缓存到redis
                    /*List<HotArticleVo> tmp = new ArrayList<>();//集合存同一个频道下的文章
                    for (HotArticleVo hotArticleVo : hotArticleVoList) {
                        if(hotArticleVo.getChannelId()!=null && hotArticleVo.getChannelId().equals(wmChannel.getId())){
                            tmp.add(hotArticleVo);
                        }
                    }*/
                    //stream流得到该频道下所有的文章
                    List<HotArticleVo> tmp = hotArticleVoList.stream().filter(x -> x.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList());
                    //缓存单个频道下的文章到redis
                    sortAndCacheArticle(tmp, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId());
                }
            }
            //缓存首页 （不区分频道，所有文章） 按分值排序后存redis
            sortAndCacheArticle(hotArticleVoList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG);
        }
    }

    /**
     * 缓存文章到redis
     * @param tmp  文章集合   安装分值降序 取前30条
     * @param s redis中key
     */
    private void sortAndCacheArticle(List<HotArticleVo> tmp, String s) {
        //按分值降序 取前30条
        List<HotArticleVo> list = tmp.stream()
                .sorted(Comparator.comparing(HotArticleVo::getScore).reversed())
                .limit(30)
                .collect(Collectors.toList());
        //缓存redis
        stringRedisTemplate.boundValueOps(s).set(JSON.toJSONString(list));
    }

    /**
     * 计算每一篇文章分值
     * @param list
     * @return
     */
    private List<HotArticleVo> computeArticleScore(List<ApArticle> list) {
        List<HotArticleVo> hotArticleVoList = new ArrayList<>();
        if(list!=null && list.size()>0){
            for (ApArticle apArticle : list) {
                HotArticleVo hotArticleVo = new HotArticleVo();
                BeanUtils.copyProperties(apArticle,  hotArticleVo);
                Integer score = computeScore(hotArticleVo);//计算文章分值
                hotArticleVo.setScore(score);
                hotArticleVoList.add(hotArticleVo);
            }
        }
        return hotArticleVoList;
    }
    //计算分值   （阅读1分  点赞3分  评论5分  收藏8分）
    private Integer computeScore(HotArticleVo hotArticleVo) {
        Integer score = 0;
        if(hotArticleVo.getLikes()!=null){
            score += hotArticleVo.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        if(hotArticleVo.getViews()!=null){
            score += hotArticleVo.getViews() * ArticleConstants.HOT_ARTICLE_VIEW_WEIGHT;
        }
        if(hotArticleVo.getComment()!=null){
            score += hotArticleVo.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if(hotArticleVo.getCollection()!=null){
            score += hotArticleVo.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }

    public static void main(String[] args) {
        Date date = DateTime.now().minusDays(5).toDate();
        System.out.println(date);


        String s = LocalDate.now().minusDays(5).toString();
        System.out.println(s);


        Date from = Date.from(LocalDateTime.now().minusDays(5).atZone(ZoneId.systemDefault()).toInstant());
        System.out.println(from);
    }

}
